<?php
	
	class DatabaseObject extends Object {
		
		/**
		* @var $translation_table - an array containing regular expression required
		* for translation from MySQL syntax to others.
		* this primarily concerns field types and some other actions that may be unavailable
		* other database systems.
		*/
		protected $translation_table = array();
		
		/**
		* @var $allowed_attributes - an associative array containing a list of all the
		* attributes that are allowed for a certain field type.
		* unsigned, for example, is not allowed for VARCHAR
		*/
		protected $allowed_attributes = array(
			'int' => array('unsigned', 'null', 'auto_increment', 'primary', 'unique'),
			'char' => array('charset','collation','null','primary','unique'),
			'varchar' => array('charset','collation','null','primary','unique'),
			'text' =>  array('charset','collation','null'),
			'float' => array('null','unique','primary')
		);
		
		protected $uniques = array();
		protected $primary_found = false;
		
		/**
		* @var $required_attributes - an associative array containig a list of required attributes
		* for a given field type.
		*/
		protected $required_attributes = array(
			'char' => array('size'),
			'varchar' => array('size')
		);
		
		protected function _unsigned($val) {
			
			return ($val ? 'UNSIGNED ' : '');
			
		}
		
		protected function _null($val) {
			
			return ($val ? 'NULL ' : 'NOT NULL ');
		
		}
		
		protected function _ai($val) {
			
			return ($val ? 'AUTO_INCREMENT ' : '');
		
		}
		
		protected function _charset($charset, $collation) {
			
			return "CHARACTER SET $charset COLLATE $collation ";
		
		}
		
		protected function _primary($val) {
			
			return ($val ? 'PRIMARY KEY ' : '');
		}
		
		protected function _comment($comment) {
			
			return 'COMMENT \''.addslashes($comment).'\' ';
		
		}
		
		protected function _onCreateField($name, $options) {
			 
			$type = $options['type'];
			#$name = $options['name'];
			$size = (array_key_exists('size',$options) ? $options['size'] : NULL);
			
			if(array_key_exists($type, $this->required_attributes) && in_array('size', $this->required_attributes[$type]) && !is_int($size)) {
				throw new MissingDbAttributeException(
					_(sprintf("Error: field type %s requires 'size' attribute (in %s)", $type, $name))
				);
			}
			
			if(is_int($size) && $size < 1) {
				//exception goes here
			}
			
			$sql = sprintf("`%s` %s ",$name, strtoupper($type));
			
			if(is_int($size)) {
				$sql .= "($size) ";
			}
			
			foreach($options as $key => &$value) {
				
				if($key == 'name' || $key == 'size' || $key == 'size') continue;
				
				if(in_array($key, $this->allowed_attributes[$type]) || $key == 'comment') {
					
					switch($key) {
						
						case 'comment':
							$sql .= $this->_comment($value);
						break;
						
						case 'unique':
							if($value) {
								$this->uniques[] = '`'.$name.'`';
							}
						break;
						
						case 'primary':
							$sql .= $this->_primary($value);
							if($this->primary_found && $value) {
								throw new DbGenericException(_('Only one primary key per table is allowed.'));
							}
							else {
								$this->primary_found = true;
							}
						break;
						
						case 'auto_increment':
							$sql .= $this->_ai($value);
						break;
						
						case 'null':
							$sql .= $this->_null($value);
						break;
						
						case 'unsigned':
							
							$sql .= $this->_unsigned($value);
						break;
					}
				}
				
			} //end foreach
			
			if(array_key_exists('charset',$options) && array_key_exists('collation', $options)) {
				$sql .= $this->_charset($options['charset'], $options['collation']);
			}
			
			return $sql;
		}
		
		
		public function onTableCreate($table, $fields) {
			
			$sql = "CREATE TABLE `$table` (";
			$first = true;
			
			foreach($fields as $key => &$value) {
				
				if($first) {
					$first = false;
				}
				
				else {
					$sql .= ',';
				}
				
				$sql .= "\n\t".$this->_onCreateField($key, $value);
				
			}
			
			if(!empty($this->uniques)) {
				$sql .= ",\n\tUNIQUE(\n\t\t".implode(',',$this->uniques)."\n\t) ";
			}
			
			$sql .= "\n)";
			
			return $sql;
		}
		
		
	
	}
	
	class DbGenericException extends Exception {
		
		public function __construct($message, $code = 0, Exception $previous = null) {
        	// some code
    	
        	// make sure everything is assigned properly
       		parent::__construct($message, $code, $previous);
    	
		}
	}
	
	class MissingDbAttributeException extends Exception {
		
		public function __construct($message, $code = 0, Exception $previous = null) {
        	// some code
    	
        	// make sure everything is assigned properly
       		parent::__construct($message, $code, $previous);
    	
		}
	}